package com.schedule.queue;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.locks.LockSupport;

public class ScheduleService {

    ExecutorService executorService = Executors.newFixedThreadPool(6);

    Trigger trigger = new Trigger();

    void schedule(Runnable task,long delay){
        ScheduleJob scheduleJob = new ScheduleJob();
        scheduleJob.setTask(task);
        scheduleJob.setStartTime(System.currentTimeMillis() + delay);
        scheduleJob.setDelay(delay);
        trigger.queue.offer(scheduleJob);
        trigger.wakeUp();
    }

    class Trigger{
        PriorityBlockingQueue<ScheduleJob> queue = new PriorityBlockingQueue<>();

        Thread thread = new Thread(()->{
           while (true){
               while (queue.isEmpty()){
                   LockSupport.park();
               }
               ScheduleJob latelyJob = queue.peek();
               if(latelyJob.getStartTime() < System.currentTimeMillis()){
                   latelyJob = queue.poll();
                   executorService.execute(latelyJob.getTask());
                   ScheduleJob job = new ScheduleJob();
                   job.setTask(latelyJob.getTask());
                   job.setDelay(latelyJob.getDelay());
                   job.setStartTime(job.getDelay() + System.currentTimeMillis());
                   queue.offer(job);
               }else{
                   LockSupport.parkUntil(latelyJob.getStartTime());
               }
           }

        });

        {
            thread.start();
            System.out.println("Trigger start");
        }

        void wakeUp(){
            LockSupport.unpark(thread);
        }
    }

}
